﻿
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;

#define NUM 8
#define PI 3.1415926

int around(double a)
{
	if (a >= 0)
	{
		return int(a + 0.5);
	}
	else
	{
		return int(a - 0.5);
	}

}
// DCT - Discrete Cosine Transform
void DCT(float data[NUM][NUM])
{
	float output[NUM][NUM];
	double alpha, beta;//C(k)  C(l)
	int m = 0, n = 0, k = 0, l = 0;
	for (k = 0; k < NUM; k++)
	{
		for (l = 0; l < NUM; l++)
		{
			if (k == 0)
			{
				alpha = sqrt(1.0 / NUM);
			}
			else
			{
				alpha = sqrt(2.0 / NUM);
			}
			if (l == 0)
			{
				beta = sqrt(1.0 / NUM);
			}
			else
			{
				beta = sqrt(2.0 / NUM);
			}
			double temp = 0.0;
			for (m = 0; m < NUM; m++)
			{
				for (n = 0; n < NUM; n++)
				{
					//int mval = data[m][n] * cos((2 * m + 1) * k * PI / (2.0 * NUM)) * cos((2 * n + 1) * l * PI / (2.0 * NUM));
					temp += data[m][n] * cos((2 * m + 1) * k * PI / (2.0 * NUM)) * cos((2 * n + 1) * l * PI / (2.0 * NUM));
				}
			}
			output[k][l] = alpha * beta * temp;// around(alpha * beta * temp);
		}
	}
	memset(data, 0, sizeof(float) * NUM * NUM);
	memcpy(data, output, sizeof(float) * NUM * NUM);

}
//Inverse DCT
void IDCT(float data[NUM][NUM])
{
	float output[NUM][NUM];
	double alpha, beta;
	int m = 0, n = 0, k = 0, l = 0;
	for (m = 0; m < NUM; m++)
	{
		for (n = 0; n < NUM; n++)
		{
			double temp = 0.0;
			for (k = 0; k < NUM; k++)
			{
				for (l = 0; l < NUM; l++)
				{
					if (k == 0)
					{
						alpha = sqrt(1.0 / NUM);
					}
					else
					{
						alpha = sqrt(2.0 / NUM);
					}
					if (l == 0)
					{
						beta = sqrt(1.0 / NUM);
					}
					else
					{
						beta = sqrt(2.0 / NUM);
					}

					temp += alpha * beta * data[k][l] * cos((2 * m + 1) * k * PI / (2 * NUM)) * cos((2 * n + 1) * l * PI / (2 * NUM));

				}
			}
			output[m][n] = around(temp);
		}
	}
	memset(data, 0, sizeof(float) * NUM * NUM);
	memcpy(data, output, sizeof(float) * NUM * NUM);

}

int main()
{
	cout.precision(5);
	float input[NUM][NUM] =
	{

			  {89, 101, 114, 125, 126, 115, 105, 96},

			  {97, 115, 131, 147, 149, 135, 123, 113},

			  {114, 134, 159, 178, 175, 164, 149, 137},

			  {121, 143, 177, 196, 201, 189, 165, 150},

			  {119, 141, 175, 201, 207, 186, 162, 144},

			  {107, 130, 165, 189, 192, 171, 144, 125},

			  {97, 119, 149, 171, 172, 145, 117, 96},

			  {88, 107, 136, 156, 155, 129, 97, 75}

	};
	int res[NUM][NUM];
	float quant[NUM][NUM] =
	{

			  {-416, -33, -60, 32, 48, -40, 0, 0},

			  {0, -24,-56, 19, 26, 0, 0, 0},

			  {-42, 13, 80, -24, -40, 0, 0, 0},

			  {-42, 17, 44, -29, 0, 0, 0, 0},

			  {18, 0, 0, 0, 0, 0, 0, 0},

			  {0, 0, 0, 0, 0, 0, 0, 0},

			  {0, 0, 0, 0, 0, 0, 0, 0},

			  {0, 0, 0, 0, 0, 0, 0, 0} 
			 /*{16, 11,10, 16, 24, 40, 51, 61},

			  {12, 12,14, 19, 26, 58, 60, 55},

			  {14, 13, 16, 24, 40, 57, 69, 56},

			  {14, 17, 22, 29, 51, 87, 80, 62},

			  {18, 22, 37, 56, 68, 109, 103, 77},

			  {24, 35, 55, 64, 81, 104, 113, 92},

			  {49, 64, 78, 87, 103, 121, 120, 101},

			  {72, 92, 95, 98, 112, 100, 103, 99}*/
	};


	cout << "The result of Array is:\n";
	for (int i = 0; i < NUM; i++)
	{
		for (int j = 0; j < NUM; j++)
		{
			input[i][j] -= 127;
			cout << input[i][j] << '\t';
		}
		cout << endl;
	}
	
	DCT(input);
	cout << "The result of DCT is:\n";
	for (int i = 0; i < NUM; i++)
	{
		for (int j = 0; j < NUM; j++)
		{
			cout << input[i][j] << '\t';
		}
		cout << endl;
	}
	cout << "quant result" << endl;
	for (int i = 0; i < NUM; i++)
	{
		for (int j = 0; j < NUM; j++)
		{
			int imt = input[i][j];
			if (imt == 0)
			{
				res[i][j] = 0;
			}else
			res[i][j] = (int)quant[i][j] / imt;
			//input[i][j] -= 127;
			cout <<(int) res[i][j] << '\t';
		}
		cout << endl;
	}

	/*IDCT(input);
	cout << "The result of IDCT is:\n";
	for (int i = 0; i < NUM; i++)
	{
		for (int j = 0; j < NUM; j++)
		{
			cout << input[i][j] << '\t';
		}
		cout << endl;
	}
	cout << "The result of input is:\n";
	for (int i = 0; i < NUM; i++)
	{
		for (int j = 0; j < NUM; j++)
		{
			cout << quant[i][j] / input[i][j] << '\t';
		}
		cout << endl;
	}*/

	return 0;
}